# coding = utf-8
import logging
import datetime

import jwt
from django.utils.encoding import smart_text
from rest_framework.authentication import BaseAuthentication, get_authorization_header
from rest_framework import exceptions, status
from django.conf import settings
from users.api.utils import jwt_decode_handler, jwt_get_username_from_payload
from users.models import UserInfo

logger = logging.getLogger("django")


def authenticate(**credentials):
    username = credentials.get("username", None)
    password = credentials.get("password", None)
    logger.info("authenticate:{},{}".format(username, password))
    if username is None or password is None:
        return None

    user = UserInfo.objects.filter(name=username, is_active=True).first()

    if user is None:
        return None

    if user.check_password(password):
        user.last_login = datetime.datetime.now()
        user.save(update_fields=["last_login"])
        return user
    else:
        return None


class JSONWebTokenAuthentication(BaseAuthentication):
    """
    Token based authentication using the JSON Web Token standard.
    """
    def authenticate(self, request):
        """
        Returns a two-tuple of `User` and token if a valid signature has been
        supplied using JWT-based authentication.  Otherwise returns `None`.
        """
        token = self.get_token_value(request)

        if token is None:
            self.error_message('没有token,请重新登录')

        try:
            payload = jwt_decode_handler(token)
            user = self.authenticate_credentials(payload)
            return (user, token)
        except jwt.ExpiredSignatureError:
            self.error_message('token 已经过期')
        except jwt.DecodeError:
            self.error_message('token 解码错误')
        except jwt.InvalidTokenError:
            self.error_message('无效token 错误')

    def authenticate_credentials(self, payload):
        """
        Returns an active user that matches the payload's user id.
        """
        user_id = jwt_get_username_from_payload(payload)

        if not user_id:
            self.error_message('非法的负载内容')

        try:
            user = UserInfo.objects.get(id=user_id)

            if not user.is_active:
                self.error_message('用户账号已被禁用')

            return user
        except UserInfo.DoesNotExist:
            self.error_message('token 非法')

    def get_token_value(self, request):
        auth = get_authorization_header(request).split()
        logger.info("request auth:{}".format(auth))
        auth_header_prefix = settings.JWT_AUTH_HEADER_PREFIX.lower()

        if not auth:
            self.error_message('没有token,请登录')

        if auth[0].lower().decode() != auth_header_prefix:
            self.error_message('Authorization格式错误!')
        if len(auth) == 1:
            self.error_message("非法的 Authorization 头. 认证信息不全!")
        elif len(auth) > 2:
            self.error_message('非法的 Authorization 头. 认证信息存在多余字符')
        return auth[1]

    def error_message(self, msg):
        msg = {
            'status_code': status.HTTP_401_UNAUTHORIZED,
            'message': msg
        }
        raise exceptions.AuthenticationFailed(msg)


